/*
 * Copyright (c) 2022 FuZhou Lockzhiner Electronic Co., Ltd. All rights reserved.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <stdio.h>
#include "los_task.h"
#include "ohos_init.h"
#include "lz_hardware.h"
#include "e53_gesture_sensor.h"
#include "MQTTClient.h"
#include "MQTTClient.h"

#define MQTT_HOST "192.168.1.15"
#define MQTT_PORT 1883

#define MQTT_PUB_TOPIC "device/BB-8/command"
#define MQTT_SUB_TOPIC "device/BB-8/report"

#define CENTER_X  150
#define CENTER_Y  150

static unsigned char sendBuf[1000];
static unsigned char readBuf[1000];

Network network;
MQTTClient client;

/***************************************************************
* 函数名称: Message_Arrived
* 说    明: 接收MQTT数据
* 参    数: data:接收的数据指针
* 返 回 值: 无
***************************************************************/
void Message_Arrived(MessageData* data)
{
    printf("Message arrived on topic %.*s: %.*s\n", data->topicName->lenstring.len, data->topicName->lenstring.data,
        data->message->payloadlen, data->message->payload);
}

/***************************************************************
* 函数名称: Iot_Mqtt_Thread
* 说    明: iot mqtt线程
* 参    数: 无
* 返 回 值: 无
***************************************************************/
void Iot_Mqtt_Thread()
{
    int rc;
    // MQTTClient client;
    MQTTMessage message;
    char payload[30];
    MQTTString clientId = MQTTString_initializer;
    MQTTPacket_connectData data = MQTTPacket_connectData_initializer;

    SetWifiModeOn();

    printf("NetworkInit...\n");
    NetworkInit(&network);

begin:
    printf("NetworkConnect...\n");
    rc = NetworkConnect(&network, MQTT_HOST, MQTT_PORT);

    printf("MQTTClientInit...\n");
    MQTTClientInit(&client, &network, 2000, sendBuf, sizeof(sendBuf), readBuf, sizeof(readBuf));

    clientId.cstring = "RK2206";

    data.clientID          = clientId;
    data.willFlag          = 0;
    data.MQTTVersion       = 3;
    data.keepAliveInterval = 0;
    data.cleansession      = 1;

    printf("MQTTConnect...\n");
    rc = MQTTConnect(&client, &data);
    if (rc != 0) {
        printf("MQTTConnect fail:%d\n", rc);
        NetworkDisconnect(&network);
        MQTTDisconnect(&client);
        LOS_Msleep(200);
        goto begin;
    }

    printf("MQTTSubscribe...\n");
    rc = MQTTSubscribe(&client, MQTT_SUB_TOPIC, 2, Message_Arrived);
    if (rc != 0) {
        printf("MQTTSubscribe fail:%d\n", rc);
        LOS_Msleep(200);
        goto begin;
    }

    while (0)
    {
        sprintf(payload, "publish test");
        message.qos = 2;
        message.retained = 0;
        message.payload = payload;
        message.payloadlen = strlen(payload);

        if ((rc = MQTTPublish(&client, MQTT_PUB_TOPIC, &message)) != 0){
            printf("Return code from MQTT publish is %d\n", rc);
            NetworkDisconnect(&network);
            MQTTDisconnect(&client);
            goto begin;
        }

        LOS_Msleep(5000);
    }
}

void e53_gs_process(void *arg)
{
    unsigned int ret = 0;
    unsigned short flag = 0;

    int rc;
    MQTTMessage message;
    char payload[30];
    int x = CENTER_X;
    int y = CENTER_Y;

    int c_prev = 0;
    int c_idx = 0;
    int colors[][3] = {
        {255,0,0},
        {0,255,0},
        {0,0,255},

        {255,255,0},
        {255,0,255},
        {0,255,255},

        {255,255,255},
    };
    int c_len = sizeof(colors)/sizeof(colors[0]);


    e53_gs_init();
    Iot_Mqtt_Thread();

    int idx = 0;

    while (1)
    {
        ret = e53_gs_get_gesture_state(&flag);
        if (ret != 0)
        {
            x = CENTER_X;
            y = CENTER_Y;

            idx ++;
            printf("Get %d Gesture Statu: 0x%x\n", idx, flag);
            if (flag & GES_UP)
            {
                printf("\tUp\n");
                y -= 50;
            }
            if (flag & GES_DOWM)
            {
                printf("\tDown\n");
                y += 50;
            }
            if (flag & GES_LEFT)
            {
                printf("\tLeft\n");
                x -= 50;
            }
            if (flag & GES_RIGHT)
            {
                printf("\tRight\n");
                x += 50;
            }
            if (flag & GES_FORWARD)
            {
                printf("\tForward\n");
                c_idx++;
            }
            if (flag & GES_BACKWARD)
            {
                printf("\tBackward\n");
            }
            if (flag & GES_CLOCKWISE)
            {
                printf("\tClockwise\n");
                // c_idx++;
            }
            if (flag & GES_COUNT_CLOCKWISE)
            {
                printf("\tCount Clockwise\n");
                // c_idx--;
            }

            if (flag & GES_WAVE)
            {
                printf("\tWave\n");
                // c_idx++;
            }
            
            e53_gs_led_up_set((flag & GES_UP) ? (1) : (0));
            e53_gs_led_down_set((flag & GES_DOWM) ? (1) : (0));
            e53_gs_led_left_set((flag & GES_LEFT) ? (1) : (0));
            e53_gs_led_right_set((flag & GES_RIGHT) ? (1) : (0));
            e53_gs_led_forward_set((flag & GES_FORWARD) ? (1) : (0));
            e53_gs_led_backward_set((flag & GES_BACKWARD) ? (1) : (0));
            e53_gs_led_cw_set((flag & GES_CLOCKWISE) ? (1) : (0));
            e53_gs_led_ccw_set((flag & GES_COUNT_CLOCKWISE) ? (1) : (0));
            e53_gs_led_wave_set((flag & GES_WAVE) ? (1) : (0));

            if(x!=CENTER_X || y!=CENTER_Y) {
                if(x<0) {
                    x = 0;
                }
                if(x>2*CENTER_X) {
                    x = CENTER_X;
                }
                if(y<0) {
                    y = 0;
                }
                if(y>2*CENTER_X) {
                    y = CENTER_X;
                }                
                sprintf(payload, "{\"action\":\"move\",\"x\":%d,\"y\":%d}", x, y);
                message.qos = 2;
                message.retained = 0;
                message.payload = payload;
                message.payloadlen = strlen(payload);

                printf("MQTT Public:%s:%s\n", MQTT_PUB_TOPIC, payload);
                if ((rc = MQTTPublish(&client, MQTT_PUB_TOPIC, &message)) != 0){
                    printf("Return code from MQTT publish is %d\n", rc);
                    NetworkDisconnect(&network);
                    MQTTDisconnect(&client);
                    // goto begin;
                }

                // LOS_Msleep(5000);
            }
            if(c_idx!=c_prev) {
                if(c_idx>=c_len) {
                    c_idx = 0;
                }
                if(c_idx<0) {
                    c_idx = c_len-1;
                }                
                sprintf(payload, "{\"action\":\"color\",\"c\":[%d,%d,%d]}", colors[c_idx][0], colors[c_idx][1], colors[c_idx][2]);
                message.qos = 2;
                message.retained = 0;
                message.payload = payload;
                message.payloadlen = strlen(payload);

                printf("MQTT Public:%s:%s\n", MQTT_PUB_TOPIC, payload);
                if ((rc = MQTTPublish(&client, MQTT_PUB_TOPIC, &message)) != 0){
                    printf("Return code from MQTT publish is %d\n", rc);
                    NetworkDisconnect(&network);
                    MQTTDisconnect(&client);
                    // goto begin;
                }
                c_prev = c_idx;
            }
        }
        else
        {
            /* 如果没有数据，则多等待 */
            LOS_Msleep(50);
        }
    }
}

void e53_gs_BB8()
{
    unsigned int thread_id;
    TSK_INIT_PARAM_S task = {0};
    unsigned int ret = LOS_OK;

    task.pfnTaskEntry = (TSK_ENTRY_FUNC)e53_gs_process;
    task.uwStackSize = 2048;
    task.pcName = "e53 getsture sensor process";
    task.usTaskPrio = 24;
    ret = LOS_TaskCreate(&thread_id, &task);
    if (ret != LOS_OK)
    {
        printf("Falied to create Task_One ret:0x%x\n", ret);
        return;
    }
}

APP_FEATURE_INIT(e53_gs_BB8);
